import cv2
import numpy as np
import time
import os


class HaarEyeDetector:
    def __init__(self):

        self.eye_closed_threshold = 10
        self.eye_detection_interval = 0.5

        self.last_eye_detection_time = 0
        self.eyes_closed_start_time = None
        self.eye_status = "open"  # 眼睛状态: open, closed


        self.face_cascade = self.load_cascade("haarcascade_frontalface_default.xml")
        self.eye_cascade = self.load_cascade("haarcascade_eye.xml")

        if self.face_cascade is None:
            print("使用OpenCV内置的人脸分类器")
            self.face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")

        if self.eye_cascade is None:
            print("使用OpenCV内置的眼睛分类器")
            self.eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_eye.xml")

        if self.face_cascade.empty():
            raise ValueError("无法加载人脸检测器")
        if self.eye_cascade.empty():
            raise ValueError("无法加载眼睛检测器")

        print("Haar分类器加载成功")

    def load_cascade(self, cascade_name):
        current_dir = os.path.dirname(os.path.abspath(__file__))
        cascade_path = os.path.join(current_dir, "..", "models", cascade_name)

        if os.path.exists(cascade_path):
            cascade = cv2.CascadeClassifier(cascade_path)
            if not cascade.empty():
                print(f"成功加载分类器: {cascade_name}")
                return cascade
            else:
                print(f"分类器文件无效: {cascade_path}")
        else:
            print(f"分类器文件不存在: {cascade_path}")

        return None

    def detect_eyes(self, frame):
        current_time = time.time()


        if current_time - self.last_eye_detection_time < self.eye_detection_interval:
            return frame, False

        self.last_eye_detection_time = current_time

        # 转换为灰度图像
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # 检测人脸
        faces = self.face_cascade.detectMultiScale(
            gray,
            scaleFactor=1.1,
            minNeighbors=5,
            minSize=(30, 30)
        )

        eyes_detected = False
        eyes_closed = False

        for (x, y, w, h) in faces:
            # 绘制人脸矩形
            cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)

            roi_gray = gray[y:y + h, x:x + w]
            roi_color = frame[y:y + h, x:x + w]

            eyes = self.eye_cascade.detectMultiScale(
                roi_gray,
                scaleFactor=1.1,
                minNeighbors=5,
                minSize=(20, 20)
            )

            # 绘制检测到的眼睛
            for (ex, ey, ew, eh) in eyes:
                cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 2)


            if len(eyes) >= 2:
                eyes_detected = True
                self.eye_status = "open"
                self.eyes_closed_start_time = None
            else:
                eyes_detected = False
                self.eye_status = "closed"

                # 记录眼睛开始闭合的时间
                if self.eyes_closed_start_time is None:
                    self.eyes_closed_start_time = current_time

                # 检查是否超过闭眼阈值
                if current_time - self.eyes_closed_start_time >= self.eye_closed_threshold:
                    eyes_closed = True

        # 在画面上显示眼睛状态
        cv2.putText(frame, f"Eyes: {self.eye_status}", (10, 30),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

        # 显示闭眼计时（如果眼睛是闭合的）
        if self.eyes_closed_start_time is not None:
            closed_duration = current_time - self.eyes_closed_start_time
            cv2.putText(frame, f"Closed: {closed_duration:.1f}s", (10, 60),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

            # 如果接近阈值，显示警告
            if closed_duration > self.eye_closed_threshold - 3:
                cv2.putText(frame, "WARNING!", (10, 90),
                            cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 3)

        return frame, eyes_closed

    def reset(self):
        """重置检测器状态"""
        self.eyes_closed_start_time = None
        self.eye_status = "open"